import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzUploadChangeParam, NzUploadFile } from 'ng-zorro-antd/upload'; // 导入事件类型
import { Observable, of } from 'rxjs';

/* 
  支持图片收缩测量源图片距离
 */


// 点坐标接口（基于图片实际像素）
interface Point {
  x: number;
  y: number;
}

// 线段测量记录接口
interface Segment {
  index: number;       // 段编号
  start: Point;        // 起点
  end: Point;          // 终点
  distance: number;    // 距离（厘米）
  color: string;       // 线段颜色
}

@Component({
  selector: 'app-demo-4',
  templateUrl: './demo-4.component.html',
  styleUrls: ['./demo-4.component.less']
})
export class Demo4Component {
  @ViewChild('measureImage') imageRef!: ElementRef<HTMLImageElement>;

  // 图片相关
  imageUrl: string | null = 'https://test.dingsing-medical.com:9000/dingsing/default/2025/10/30/95e777bc3efa4f72a702f9e9b9b5425f.jpg'; // 当前测量图片URL
  // imageUrl: string | null = null; // 当前测量图片URL
  isUploading = false; // 上传状态
  // 上传接口（官方示例地址，实际项目替换为你的后端接口）
  uploadAction = 'https://yeyuge.gz.cn/api/file/upload';
  // uploadAction = 'https://test.dingsing-medical.com/api/file/upload';
  // uploadAction = 'https://www.mocky.io/v2/5cc8019d300000980a055e76';
  uploadHeaders = { authorization: 'authorization-text' };


  // 测量相关
  private colorPalette = [
    '#ff4d4f', '#1890ff', '#52c41a', '#faad14', '#722ed1',
    '#f5222d', '#13c2c2', '#fa8c16', '#7cb305', '#3166ff'
  ];
  segments: Segment[] = []; // 已完成的测量段
  currentSegment: { index: number; start: Point; color: string } | null = null; // 当前测量段
  tempPoint: Point | null = null; // 鼠标临时点
  currentTempDistance = 0; // 当前临时距离
  showTempDistance = false; // 是否显示临时距离
  private pixelsPerCm = 0; // 每厘米像素数
  private basePixelsPerCm = 0; // 基础像素/厘米（理论值）
  calibrateRatio = 1; // 校准比例（默认1，无误差）
  screenError = 1; // 屏幕误差比例（默认1，无误差）

  constructor(private message: NzMessageService) { }

  ngOnInit(): void {
    // 初始化屏幕DPI转厘米像素比（1英寸=2.54厘米）
    const dpr = window.devicePixelRatio || 1;
    // this.pixelsPerCm = (96 * dpr) / 2.54;
    this.basePixelsPerCm = (96 * dpr) / 2.54;
  }

  // 生成随机 HSL 颜色（可自定义饱和度/亮度）
  getRandomHexColor() {
    // Math.random() 生成 0-1 小数 → 乘 0xffffff 得到 0-16777215 的数 → 转 16 进制 → 补零到 6 位
    return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
  }

  // 处理上传状态变化（核心修改：使用nzChange替代nzBeforeUpload）
  handleChange(info: NzUploadChangeParam): void {
    const file = info.file; // 获取当前操作的文件

    // 上传开始
    if (file.status === 'uploading') {
      this.isUploading = true;
      return;
    }

    // 上传成功
    if (file.status === 'done') {
      this.isUploading = false;
      // 1. 优先使用本地文件预览（即使上传到服务器，也先显示本地图片）
      if (file.originFileObj) {
        this.readLocalFile(file.originFileObj);
      } else {
        // 2. 若本地文件不存在（如从服务器获取的历史文件），使用返回的URL
        this.imageUrl = (file.response as any)?.url || null;
        if (this.imageUrl) {
          this.resetAll();
          this.message.success('图片上传成功');
        } else {
          this.message.error('图片上传成功，但无法获取图片URL');
        }
      }
      return;
    }

    // 上传失败
    if (file.status === 'error') {
      this.isUploading = false;
      this.message.error('图片上传失败，请重试');
    }
  }

  // 读取本地文件并预览（提取原handleUpload的核心逻辑）
  private readLocalFile(file: File): void {
    if (!this.isImageFile(file)) {
      this.message.error('请上传有效的图片文件（jpg、png、jpeg格式）');
      return;
    }

    const reader = new FileReader();
    reader.onload = (e: ProgressEvent<FileReader>) => {
      this.imageUrl = e.target?.result as string;
      this.resetAll(); // 重置测量数据
      this.message.success('图片上传成功，可开始测量');
    };
    reader.onerror = () => {
      this.message.error('图片读取失败，请重试');
    };
    reader.readAsDataURL(file);
  }

  // 补充：图片文件验证方法（关键修复）
  private isImageFile(file: File): boolean {
    const isImageType = file.type.startsWith('image/');
    const fileName = file.name.toLowerCase();
    const validExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'];
    const isValidExt = validExts.some(ext => fileName.endsWith(ext));
    return isImageType && isValidExt;
  }


  // 图片点击事件（记录测量点）
  onImageClick(event: MouseEvent): void {
    if (!this.imageUrl) {
      this.message.warning('请先上传图片');
      return;
    }

    const imagePoint = this.getImageRelativePoint(event);
    if (!this.currentSegment) {
      // 开始新线段（奇数点击）
      const segmentIndex = this.segments.length + 1;
      this.currentSegment = {
        index: segmentIndex,
        start: imagePoint,
        color: this.getRandomHexColor()
        // color: this.colorPalette[segmentIndex % this.colorPalette.length]
      };
      this.showTempDistance = true;
    } else {
      // 完成当前线段（偶数点击）
      const distance = this.calculateDistance(
        this.currentSegment.start,
        imagePoint
      );
      this.segments.push({
        index: this.currentSegment.index,
        start: this.currentSegment.start,
        end: imagePoint,
        distance,
        color: this.currentSegment.color
      });
      this.currentSegment = null;
      this.tempPoint = null;
      this.showTempDistance = false;
    }
  }

  // 新增：跟踪鼠标在测量容器内的位置
  mouseX = 0;
  mouseY = 0;

  // 简化校准：输入比例后确认（核心新增）
  confirmRatioCalibrate(): void {
    if (this.calibrateRatio <= 0) {
      this.message.warning('请输入大于0的校准比例');
      return;
    }
    // 重置现有测量数据，确保新比例生效
    this.resetAll();
    this.message.success(`校准完成！比例：${this.calibrateRatio}`);
  }


  // 优化鼠标移动事件：记录鼠标位置用于准星显示
  onImageMouseMove(event: MouseEvent): void {
    if (!this.imageUrl) return;

    // 记录鼠标在测量容器内的坐标（用于十字准星定位）
    const wrapper = this.imageRef.nativeElement.parentElement;
    if (wrapper) {
      const rect = wrapper.getBoundingClientRect();
      this.mouseX = event.clientX - rect.left;
      this.mouseY = event.clientY - rect.top;
    }

    // 原有临时点计算逻辑
    if (this.currentSegment) {
      this.tempPoint = this.getImageRelativePoint(event);
      if (this.tempPoint) {
        this.currentTempDistance = this.calculateDistance(
          this.currentSegment.start,
          this.tempPoint
        );
      }
    }
  }

  // 计算两点距离（厘米）
  private calculateDistance(p1: Point, p2: Point): number {
    const dx = p2.x - p1.x;
    const dy = p2.y - p1.y;
    const pixelDistance = Math.sqrt(dx * dx + dy * dy);
    // console.log(pixelDistance, 'pixelDistance===');

    // return pixelDistance / this.pixelsPerCm;
    // 修正公式：原始距离 / 校准比例 = 准确距离
    return (pixelDistance / this.basePixelsPerCm) / this.calibrateRatio / this.screenError;
  }


  // 优化：更精确的坐标转换（考虑图片容器的滚动和偏移）
  private getImageRelativePoint(event: MouseEvent): Point {
    const image = this.imageRef.nativeElement;
    const imageRect = image.getBoundingClientRect(); // 图片在视口中的位置
    const wrapper = image.parentElement; // 测量容器（.measure-wrapper）
    if (!wrapper) return { x: 0, y: 0 };

    const wrapperRect = wrapper.getBoundingClientRect(); // 容器在视口中的位置

    // 计算点击位置相对于图片的偏移（修正容器滚动和边框影响）
    const clickX = event.clientX - imageRect.left;
    const clickY = event.clientY - imageRect.top;

    // 计算图片实际尺寸与显示尺寸的缩放比例
    const scaleX = image.naturalWidth / imageRect.width;
    const scaleY = image.naturalHeight / imageRect.height;

    // 计算基于图片实际像素的坐标（四舍五入到整数像素）
    return {
      x: Math.round(clickX * scaleX),
      y: Math.round(clickY * scaleY)
    };
  }

  // 计算线段显示长度（基于图片显示尺寸）
  getLineLength(p1: Point, p2: Point): number {
    const image = this.imageRef.nativeElement;
    const rect = image.getBoundingClientRect();
    const scale = rect.width / image.naturalWidth; // 显示尺寸缩放比例
    const dx = p2.x - p1.x;
    const dy = p2.y - p1.y;
    return Math.sqrt(dx * dx + dy * dy) * scale;
  }

  // 计算线段旋转角度（用于显示）
  getLineTransform(p1: Point, p2: Point): string {
    const angle = Math.atan2(p2.y - p1.y, p2.x - p1.x) * (180 / Math.PI);
    return `rotate(${angle}deg) translate(0, -50%)`;
  }

  // 将图片实际坐标转换为显示坐标
  getDisplayPosition(value: number, isX: boolean): number {
    const image = this.imageRef.nativeElement;
    const rect = image.getBoundingClientRect();
    const scale = isX
      ? rect.width / image.naturalWidth
      : rect.height / image.naturalHeight;
    return value * scale;
  }

  // 删除指定测量段
  deleteSegment(index: number): void {
    this.segments = this.segments.filter(seg => seg.index !== index);
    // 重新编号保持连续性
    this.segments.forEach((seg, i) => seg.index = i + 1);
  }

  // 重置所有测量数据
  resetAll(): void {
    this.segments = [];
    this.currentSegment = null;
    this.tempPoint = null;
    this.currentTempDistance = 0;
    this.showTempDistance = false;
  }

  // ngFor优化跟踪函数
  trackByIndex(index: number): number {
    return index;
  }
}
